/**
 * https://github.com/brattonross/vite-plugin-voie/blob/main/packages/vite-plugin-voie/src/options.ts
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file at
 * https://github.com/brattonross/vite-plugin-voie/blob/main/LICENSE
 */

export type ImportMode = 'sync' | 'async'
export type ImportModeResolveFn = (filepath: string) => ImportMode

export interface Route {
  name?: string
  key?: string
  path: string
  props?: boolean | Record<string, any> | ((to: any) => Record<string, any>)
  component: string
  children?: Route[]
  routes?: Route[]
  exact?: boolean
  meta?: Record<string, unknown>
  beforeEnter?: any

  // internal props
  variables?: string[]
  isMatchAll?: boolean

  [x: string]: any
}

export interface PageDirOptions {
  dir: string
  baseRoute: string
  /**
   * Valid file extensions for page components.
   * @default UserOptions['extensions']
   */
  extensions?: string[]
  /**
   * List of path globs to exclude when resolving pages.
   */
  exclude?: string[]
  /**
   * A function that takes a route and optionally returns a modified route.
   * This is useful for augmenting your routes with extra data (e.g. route metadata).
   */
  extendRoute?: (route: Route, parent?: Route) => Route | void
}

/**
 * Plugin options.
 */
interface Options {
  /**
   * Relative path to the directory to search for page components.
   * @default 'src/pages'
   */
  pagesDir: string | (string | PageDirOptions)[]
  /**
   * Valid file extensions for page components.
   * @default ['vue','tsx','ts','jsx','js']
   */
  extensions: string[]
  /**
   * List of path globs to exclude when resolving pages.
   */
  exclude: string[]
  /**
   * Import routes directly or as async components
   * @default 'async'
   */
  importMode: ImportMode | ImportModeResolveFn
  /**
   * Sync load top level index file
   * @default true
   */
  syncIndex: boolean
  /**
   * Use Nuxt.js style dynamic routing
   * @default false
   */
  nuxtStyle: boolean
  /**
   * Enable route block scanner
   * @default false
   */
  enableRouteBlock: boolean
  /**
   * Set default route block parser, or use `<route lang=xxx>` in SFC route block
   * @default 'json5'
   */
  routeBlockLang: 'json5' | 'json' | 'yaml' | 'yml'
  /**
   * Replace '[]' to '_' in bundle chunk filename
   * Experimental feature
   * @default true
   */
  keepExtraAttrs: boolean | string[]
  replaceSquareBrackets: boolean
  /**
   * Replace dynamiRoute pattern
   * @example
   * config: `
   *   replaceDynamicPatterns: {
   *     age: '\\d{1,3}'
   *   }
   * `
   * generated: '/src/[a:age]' ==> '/src/:a(\\d{1,3})'
   */
  replaceDynamicPatterns: Record<string, string>
  /**
   * Generate React Route
   * @default false
   */
  react: boolean
  /**
   * A function that takes a route and optionally returns a modified route.
   * This is useful for augmenting your routes with extra data (e.g. route metadata).
   */
  extendRoute: (route: Route, parent?: Route) => Route | void
}

export type UserOptions = Partial<Options>

export interface ResolvedOptions extends Omit<Options, 'pagesDir' | 'extendRoute'> {
  /**
   * Resolves to the `root` value from Vite config.
   * @default config.root
   */
  root: string
  pagesDir: (Omit<Required<PageDirOptions>, 'extendRoute'> & {
    extendRoute: (route: Route, parent?: Route) => Route
    extensionsRE: RegExp
  })[]
  isbuild: boolean
}
